package com.cms.security;

import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;

import com.cms.entity.Action;
import com.cms.entity.Role;
import com.cms.service.ActionService;

public class SecurityMetadataSource implements
		FilterInvocationSecurityMetadataSource {
	private static final Logger LOGGER = LoggerFactory
			.getLogger(SecurityMetadataSource.class);

	private ConfigAttribute defaultConfig;
	private Collection<ConfigAttribute> defaultAttributs;
	private Map<String, Collection<ConfigAttribute>> resourcesMap;

	@Autowired
	private ActionService actionService;
	
	public SecurityMetadataSource(){
		LOGGER.info("------------------do SecurityMetadataSource----------------");
	}
	

	public Collection<ConfigAttribute> getAttributes(Object object)
			throws IllegalArgumentException {
		init();
		String url = ((FilterInvocation) object).getRequestUrl();
		String baseUrl = url.replaceAll("\\?.*$", "").substring(1);
		Collection<ConfigAttribute> attr = resourcesMap.get(baseUrl);
		return attr != null ? attr : defaultAttributs;
	}

	public Collection<ConfigAttribute> getAllConfigAttributes() {
		return null;
	}

	public boolean supports(Class<?> clazz) {
		return true;
	}

	public void init() {
		defaultConfig = new SecurityConfig("ROLE_NONE");
		defaultAttributs = Arrays.asList(defaultConfig);
		resourcesMap = new ConcurrentHashMap<String, Collection<ConfigAttribute>>();
		for (Action action : actionService.listActions()) {
			if (action.getUrl() == null) {
				LOGGER.debug("skip action without url: %s", action.getTitle());
				continue;
			}
			Set<ConfigAttribute> attr = new HashSet<ConfigAttribute>();
			for (Role role : action.getRoles()) {
				LOGGER.debug("grant role [%s] to url [%s]",
						role.getAuthority(), action.getUrl());
				attr.add(new SecurityConfig(role.getAuthority()));
			}
			if (attr.isEmpty()) {
				attr.add(defaultConfig);
			}
			resourcesMap.put(action.getUrl(), attr);
		}
	}

	public ConfigAttribute getDefaultConfig() {
		return defaultConfig;
	}

	public void setDefaultConfig(ConfigAttribute defaultConfig) {
		this.defaultConfig = defaultConfig;
	}

	public Collection<ConfigAttribute> getDefaultAttributs() {
		return defaultAttributs;
	}

	public void setDefaultAttributs(Collection<ConfigAttribute> defaultAttributs) {
		this.defaultAttributs = defaultAttributs;
	}

	public Map<String, Collection<ConfigAttribute>> getResourcesMap() {
		return resourcesMap;
	}

	public void setResourcesMap(
			Map<String, Collection<ConfigAttribute>> resourcesMap) {
		this.resourcesMap = resourcesMap;
	}

	public ActionService getActionService() {
		return actionService;
	}

	public void setActionService(ActionService actionService) {
		this.actionService = actionService;
	}
}
